package com.px.gis.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.px.gis.entity.Area;
import com.px.gis.mapper.AreaMapper;
import com.px.gis.service.IAreaService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements IAreaService {


    @Override
    public boolean saveEntity(Area entity) {
        if (null != entity.getPolygonPoints()) {
            String[] points = toGeom(entity.getPolygonPoints()).split(",");
            if (!StrUtil.equals(points[0], points[points.length - 1])) {
                throw new RuntimeException("传入的经纬度不是一个闭合区域,最后一个点应该等于第一个点");
            }
        }

        if (StrUtil.isBlank(entity.getIdPath())) {
            // 更新前删除原数据
            Area old = getById(entity.getAreaId());
            if (null != old) {
                lambdaUpdate().likeRight(Area::getIdPath, old.getIdPath()).remove();
            }
            // 设置id路径
            entity.setIdPath(entity.getAreaId() + "_");
        }
        saveOrUpdate(entity);

        // 矩形
        if (CollUtil.isNotEmpty(entity.getPolygonPoints())) {
            String geom = toGeom(entity.getPolygonPoints());
            baseMapper.updatePolygon(entity.getAreaId(), geom);
        }else {
            // 圆形
            if (0 == entity.getShape()) {
                baseMapper.updateCircle(entity.getAreaId(), entity.getLng(), entity.getLat(), entity.getRadius());
            }
        }
        if (CollUtil.isNotEmpty(entity.getSubAreas())) {
            entity.getSubAreas().forEach(i -> {
                i.setParentId(entity.getAreaId());
                i.setIdPath(entity.getIdPath() + i.getAreaId() + "_");
                saveEntity(i);
            });
        }

        return true;
    }

    @Override
    public List<Area> intersects(String polygon) {
        List<Area> intersects = baseMapper.intersects(polygon);
        if (CollUtil.isEmpty(intersects)) {
            return new ArrayList<>();
        }

        List<Long> topAreaId = intersects.stream().map(i -> i.getIdPath().split("_")[0])
                .map(NumberUtil::parseLong).distinct().collect(Collectors.toList());

        String where = topAreaId.stream()
                .map(idPath -> " id_path like '"+ idPath + "_%'")
                .collect(Collectors.joining(" or "));
        List<Area> allArea = baseMapper.likeRightByIdPath(where);

        allArea.forEach(area -> {
            JSONObject json = JSONUtil.parseObj(area.getPolygonJson());
            area.setPolygonPoints(json.getJSONArray("coordinates"));
            if (0 == area.getShape()) {
                area.setPolygonPoints(null);
            }
        });
        return allArea;
    }

    @Override
    public void removeEntity(Long id) {
        Area area = getById(id);
        if (null != area) {
            lambdaUpdate().likeRight(Area::getIdPath, area.getIdPath()).remove();
        }
    }

    @Override
    public List<Tree<Long>> getTrees(List<Area> allArea) {
        TreeNodeConfig config = new TreeNodeConfig();
        // 树形数据中id的属性名,写成id1方便区分,实际上写AClothClassVo实体类的id属性名
        config.setIdKey("areaId");
        config.setParentIdKey("parentId");
        config.setNameKey("name");
        config.setChildrenKey("sub_areas");
        config.setDeep(4);

        List<Tree<Long>> name = TreeUtil.build(allArea, null, config, (node, tree) -> {
            tree.setId(node.getAreaId());
            tree.setParentId(node.getParentId());
            tree.putExtra("name", node.getName());
            tree.putExtra("color", node.getColor());
            tree.putExtra("height", node.getHeight());
            tree.putExtra("address", node.getAddress());
            tree.putExtra("begin_at", node.getBeginAt());
            tree.putExtra("city", node.getCity());
            tree.putExtra("country", node.getCountry());
            tree.putExtra("data_source", node.getDataSource());
            tree.putExtra("description", node.getDescription());
            tree.putExtra("end_at", node.getEndAt());
            tree.putExtra("lat", node.getLat());
            tree.putExtra("lng", node.getLng());
            tree.putExtra("level", node.getLevel());
            tree.putExtra("radius", node.getRadius());
            tree.putExtra("shape", node.getShape());
            tree.putExtra("type", node.getType());
            tree.putExtra("url", node.getUrl());
            tree.putExtra("external", node.isExternal());
            tree.putExtra("polygon_points", node.getPolygonPoints());
            tree.putExtra("idPath", node.getIdPath());
        });
        return name;
    }

    private String toGeom(JSONArray polygonPoints) {
        return ((List<List<Object>>)polygonPoints.get(0))
                .stream().map(c-> c.stream().map(s -> s + "").collect(Collectors.joining(" ")))
                .collect(Collectors.joining(","));
    }


}
